#include "viml/builtin_string.h"
#include "viml/value.h"
#include "viml/vm.h"
#include <algorithm>
#include <stdexcept>
#include <cmath>
#include <cctype>
#include <regex>

namespace viml {

// len({str}) - 返回字符串的字符数 (也可以处理list和dict)
Value len_string_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("len() requires exactly 1 argument");
    }
    
    // 检查参数类型
    const auto& arg = args[0];
    if (arg.is_string()) {
        // 对于字符串，返回字符数而不是字节数
        // 简化处理：假设ASCII字符，实际实现可能需要更复杂的unicode处理
        return Value::make_number(static_cast<int64_t>(arg.as_string().length()));
    } else if (arg.is_list()) {
        return Value::make_number(static_cast<int64_t>(arg.as_list().size()));
    } else if (arg.is_dict()) {
        return Value::make_number(static_cast<int64_t>(arg.as_dict().size()));
    } else {
        throw std::runtime_error("len() argument must be a string, list, or dict");
    }
}

// empty({str}) - 判断字符串是否为空
Value empty_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("empty() requires exactly 1 argument");
    }
    
    // 检查参数类型是否为字符串
    const auto& arg = args[0];
    if (!arg.is_string()) {
        throw std::runtime_error("empty() argument must be a string");
    }
    
    // 判断字符串长度是否为0
    return Value::boolean(arg.as_string().empty());
}

// stridx({haystack}, {needle} [, {start}]) - 返回子串第一次出现的索引
Value stridx_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() < 2 || args.size() > 3) {
        throw std::runtime_error("stridx() requires 2 or 3 arguments");
    }
    
    // 检查参数类型
    if (!args[0].is_string() || !args[1].is_string()) {
        throw std::runtime_error("stridx() first two arguments must be strings");
    }
    
    const std::string& haystack = args[0].as_string();
    const std::string& needle = args[1].as_string();
    
    // 确定起始搜索位置
    size_t start_pos = 0;
    if (args.size() == 3) {
        int64_t start = args[2].to_number();
        // VimL索引从1开始，转换为C++索引从0开始
        if (start > 0) {
            start_pos = static_cast<size_t>(start - 1);
        } else if (start < 0) {
            // 负索引处理
            if (static_cast<size_t>(std::abs(start)) <= haystack.length()) {
                start_pos = static_cast<size_t>(haystack.length()) + static_cast<size_t>(start);
            }
        }
    }
    
    // 查找子串
    size_t pos = haystack.find(needle, start_pos);
    
    // 返回结果（VimL索引从1开始，未找到返回-1）
    if (pos != std::string::npos) {
        return Value::make_number(static_cast<int64_t>(pos + 1));
    } else {
        return Value::make_number(-1);
    }
}

// strridx({haystack}, {needle} [, {start}]) - 返回子串最后一次出现的索引
Value strridx_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() < 2 || args.size() > 3) {
        throw std::runtime_error("strridx() requires 2 or 3 arguments");
    }
    
    // 检查参数类型
    if (!args[0].is_string() || !args[1].is_string()) {
        throw std::runtime_error("strridx() first two arguments must be strings");
    }
    
    const std::string& haystack = args[0].as_string();
    const std::string& needle = args[1].as_string();
    
    // 确定起始搜索位置
    size_t start_pos = std::string::npos;
    if (args.size() == 3) {
        int64_t start = args[2].to_number();
        // VimL索引从1开始，转换为C++索引从0开始
        if (start > 0) {
            // In VimL, for strridx, start parameter limits the search to the range [0, start]
            if (static_cast<size_t>(start) <= haystack.length()) {
                start_pos = static_cast<size_t>(start - 1);
            }
        } else if (start < 0) {
            // 负索引处理
            if (static_cast<size_t>(std::abs(start)) <= haystack.length()) {
                start_pos = static_cast<size_t>(haystack.length()) + static_cast<size_t>(start);
            }
        }
    }
    
    // 查找子串最后一次出现的位置
    size_t pos = haystack.rfind(needle, start_pos);
    
    // 返回结果（VimL索引从1开始，未找到返回-1）
    if (pos != std::string::npos) {
        return Value::make_number(static_cast<int64_t>(pos + 1));
    } else {
        return Value::make_number(-1);
    }
}

// strpart({str}, {start} [, {len}]) - 截取子字符串
Value strpart_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() < 2 || args.size() > 3) {
        throw std::runtime_error("strpart() requires 2 or 3 arguments");
    }
    
    // 检查参数类型
    if (!args[0].is_string()) {
        throw std::runtime_error("strpart() first argument must be a string");
    }
    
    const std::string& str = args[0].as_string();
    int64_t start = args[1].to_number();
    
    // VimL索引从1开始，转换为C++索引从0开始
    int64_t cpp_start = start - 1;
    
    // 处理负索引
    if (cpp_start < 0) {
        cpp_start = static_cast<int64_t>(str.length()) + cpp_start + 1;
    }
    
    // 检查起始位置是否有效
    if (cpp_start < 0 || static_cast<size_t>(cpp_start) >= str.length()) {
        return Value::string("");
    }
    
    // 确定截取长度
    size_t length = std::string::npos;
    if (args.size() == 3) {
        int64_t len = args[2].to_number();
        if (len < 0) {
            length = 0;
        } else {
            length = static_cast<size_t>(len);
        }
    }
    
    // 截取子字符串
    std::string result = str.substr(static_cast<size_t>(cpp_start), length);
    
    return Value::string(result);
}

// tolower({str}) - 将字符串转为小写
Value tolower_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("tolower() requires exactly 1 argument");
    }
    
    // 检查参数类型
    if (!args[0].is_string()) {
        throw std::runtime_error("tolower() argument must be a string");
    }
    
    std::string result = args[0].as_string();
    
    // 转换为小写
    std::transform(result.begin(), result.end(), result.begin(),
                   [](unsigned char c) { return std::tolower(c); });
    
    return Value::string(result);
}

// toupper({str}) - 将字符串转为大写
Value toupper_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("toupper() requires exactly 1 argument");
    }
    
    // 检查参数类型
    if (!args[0].is_string()) {
        throw std::runtime_error("toupper() argument must be a string");
    }
    
    std::string result = args[0].as_string();
    
    // 转换为大写
    std::transform(result.begin(), result.end(), result.begin(),
                   [](unsigned char c) { return std::toupper(c); });
    
    return Value::string(result);
}

// substitute({str}, {pattern}, {replacement} [, {flags}]) - 字符串替换
Value substitute_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() < 3 || args.size() > 4) {
        throw std::runtime_error("substitute() requires 3 or 4 arguments");
    }
    
    // 检查参数类型
    if (!args[0].is_string() || !args[1].is_string() || !args[2].is_string()) {
        throw std::runtime_error("substitute() first three arguments must be strings");
    }
    
    std::string result = args[0].as_string();
    const std::string& pattern = args[1].as_string();
    const std::string& replacement = args[2].as_string();
    
    // 处理标志参数
    std::string flags = "";
    if (args.size() == 4) {
        if (!args[3].is_string()) {
            throw std::runtime_error("substitute() fourth argument must be a string");
        }
        flags = args[3].as_string();
    }
    
    try {
        // 创建正则表达式对象
        std::regex_constants::syntax_option_type regex_flags = std::regex_constants::ECMAScript;
        if (flags.find('i') != std::string::npos) {
            regex_flags |= std::regex_constants::icase;
        }
        
        std::regex reg(pattern, regex_flags);
        
        // 执行替换
        if (flags.find('g') != std::string::npos) {
            // 全局替换
            result = std::regex_replace(result, reg, replacement);
        } else {
            // 只替换第一个匹配项
            result = std::regex_replace(result, reg, replacement, std::regex_constants::format_first_only);
        }
    } catch (const std::regex_error& e) {
        throw std::runtime_error("Invalid regex pattern in substitute(): " + std::string(e.what()));
    }
    
    return Value::string(result);
}

// split({str} [, {pattern} [, {keepempty}]]) - 将字符串按分隔符拆分为List
Value split_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() < 1 || args.size() > 3) {
        throw std::runtime_error("split() requires 1 to 3 arguments");
    }
    
    // 检查第一个参数类型
    if (!args[0].is_string()) {
        throw std::runtime_error("split() first argument must be a string");
    }
    
    const std::string& str = args[0].as_string();
    
    // 确定分隔符模式
    std::string pattern = "\\s+"; // 默认为空白字符
    if (args.size() >= 2) {
        if (!args[1].is_string()) {
            throw std::runtime_error("split() second argument must be a string");
        }
        pattern = args[1].as_string();
        if (pattern.empty()) {
            pattern = "\\s+";
        }
    }
    
    // 确定是否保留空元素
    bool keepempty = false;
    if (args.size() == 3) {
        keepempty = args[2].is_truthy();
    }
    
    // 创建结果列表
    Value result_list = Value::list();
    auto& elements = result_list.as_list();
    
    try {
        // 使用正则表达式进行分割
        std::regex reg(pattern);
        std::sregex_token_iterator iter(str.begin(), str.end(), reg, -1);
        std::sregex_token_iterator end;
        
        for (; iter != end; ++iter) {
            std::string token = *iter;
            if (keepempty || !token.empty()) {
                elements.push_back(Value::string(token));
            }
        }
    } catch (const std::regex_error& e) {
        throw std::runtime_error("Invalid regex pattern in split(): " + std::string(e.what()));
    }
    
    return result_list;
}

// join({list} [, {separator}]) - 将List拼接成一个字符串
Value join_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() < 1 || args.size() > 2) {
        throw std::runtime_error("join() requires 1 or 2 arguments");
    }
    
    // 检查第一个参数类型
    if (!args[0].is_list()) {
        throw std::runtime_error("join() first argument must be a list");
    }
    
    const auto& list = args[0].as_list();
    
    // 确定分隔符
    std::string separator = " "; // 默认为空格
    if (args.size() == 2) {
        if (!args[1].is_string()) {
            throw std::runtime_error("join() second argument must be a string");
        }
        separator = args[1].as_string();
    }
    
    // 拼接字符串
    std::string result;
    for (size_t i = 0; i < list.size(); ++i) {
        if (i > 0) {
            result += separator;
        }
        // 使用Value的to_string方法来正确转换所有类型
        result += list[i].to_string();
    }
    
    return Value::string(result);
}

// string(x) - 将任意类型转为字符串
Value string_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("string() requires exactly 1 argument");
    }
    
    // 使用Value类的to_string方法
    return Value::string(args[0].to_string());
}

} // namespace viml